/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <memory>
#include <vector>
#include <optional>

// 前向声明，避免复杂的include依赖
namespace dev {
    class hi182x_card;
    class imu;
}

namespace dev {

// 模拟imu_pcie_device_req_t结构，用于测试
struct imu_pcie_device_req_t {
    uint8_t system_id;
    uint8_t socket_id;
    uint8_t bus;
    uint8_t device;
    uint8_t function;
    uint8_t pci_info_address;
    uint8_t rlen;
};

// 模拟IMU类，用于测试
class MockIMU {
public:
    MockIMU() = default;
    
    // 模拟get_info_from_imu方法
    std::optional<std::vector<uint8_t>> get_info_from_imu(
        bool is_local, const imu_pcie_device_req_t& pcie_device_info) {
        // 根据地址返回不同的测试数据
        if (pcie_device_info.pci_info_address == 0x00) {  // VID_DID_ADDRESS
            // VID=0x19e5, DID=0x1822 (little-endian)
            return std::vector<uint8_t>{0xe5, 0x19, 0x22, 0x18};
        } else if (pcie_device_info.pci_info_address == 0x2C) {  // SVID_SDID_ADDRESS
            // SVID=0x19e5, SDID=0x1823 (little-endian)
            return std::vector<uint8_t>{0xe5, 0x19, 0x23, 0x18};
        }
        return std::nullopt;
    }
};

// 模拟hi182x_card类，用于测试新增的方法
class MockHi182xCard {
public:
    MockHi182xCard() : m_imu_obj(std::make_shared<MockIMU>()) {
        // 初始化测试数据
        m_system_id = 1;
        m_pcie_device_bus = 1;
        m_pcie_device_device = 0;
        m_pcie_device_function = 0;
        m_pcie_device_socket_id = 0;
        m_power_state = "ON";  // 默认电源开启
    }
    
    // 设置无效BDF
    void set_invalid_bdf() {
        m_pcie_device_bus = 0;
        m_pcie_device_device = 0;
        m_pcie_device_function = 0;
    }
    
    // 设置电源关闭
    void set_power_off() {
        m_power_state = "OFF";
    }
    
    // 清空IMU对象
    void clear_imu() {
        m_imu_obj = nullptr;
    }
    
    // 测试get_pcie_vid_did_info方法
    bool get_pcie_vid_did_info(uint16_t& vendor_id, uint16_t& device_id) {
        if (!m_imu_obj) {
            return false;
        }
        
        // 构造PCI设备请求信息
        imu_pcie_device_req_t pcie_device_info = {
            .system_id = m_system_id,
            .socket_id = m_pcie_device_socket_id,
            .bus = m_pcie_device_bus,
            .device = m_pcie_device_device,
            .function = m_pcie_device_function,
            .pci_info_address = 0x00,  // VID_DID_ADDRESS
            .rlen = 4
        };
        
        auto result = m_imu_obj->get_info_from_imu(true, pcie_device_info);
        if (!result || result->size() < 4) {
            return false;
        }
        
        // 解析VID/DID (little-endian)
        vendor_id = ((*result)[1] << 8) | (*result)[0];
        device_id = ((*result)[3] << 8) | (*result)[2];
        
        // 检查有效性
        if (vendor_id == 0xFFFF || device_id == 0xFFFF) {
            return false;
        }
        
        return true;
    }
    
    // 测试get_pcie_svid_sdid_info方法
    bool get_pcie_svid_sdid_info(uint16_t& subsystem_vendor_id, uint16_t& subsystem_device_id) {
        if (!m_imu_obj) {
            return false;
        }
        
        // 构造PCI设备请求信息
        imu_pcie_device_req_t pcie_device_info = {
            .system_id = m_system_id,
            .socket_id = m_pcie_device_socket_id,
            .bus = m_pcie_device_bus,
            .device = m_pcie_device_device,
            .function = m_pcie_device_function,
            .pci_info_address = 0x2C,  // SVID_SDID_ADDRESS
            .rlen = 4
        };
        
        auto result = m_imu_obj->get_info_from_imu(false, pcie_device_info);
        if (!result || result->size() < 4) {
            return false;
        }
        
        // 解析SVID/SDID (little-endian)
        subsystem_vendor_id = ((*result)[1] << 8) | (*result)[0];
        subsystem_device_id = ((*result)[3] << 8) | (*result)[2];
        
        // 检查有效性
        if (subsystem_vendor_id == 0xFFFF || subsystem_device_id == 0xFFFF) {
            return false;
        }
        
        return true;
    }
    
    // 测试get_network_adapter_quadruple方法
    bool get_network_adapter_quadruple() {
        uint16_t vendor_id, device_id, subsystem_vendor_id, subsystem_device_id;
        
        // 获取VID/DID
        if (!get_pcie_vid_did_info(vendor_id, device_id)) {
            return false;
        }
        
        // 获取SVID/SDID
        if (!get_pcie_svid_sdid_info(subsystem_vendor_id, subsystem_device_id)) {
            return false;
        }
        
        // 格式化并存储四元组信息
        char vid_str[16], did_str[16], svid_str[16], sdid_str[16];
        snprintf(vid_str, sizeof(vid_str), "0x%04x", vendor_id);
        snprintf(did_str, sizeof(did_str), "0x%04x", device_id);
        snprintf(svid_str, sizeof(svid_str), "0x%04x", subsystem_vendor_id);
        snprintf(sdid_str, sizeof(sdid_str), "0x%04x", subsystem_device_id);
        
        m_vendor_id_str = vid_str;
        m_device_id_str = did_str;
        m_subsystem_vendor_id_str = svid_str;
        m_subsystem_device_id_str = sdid_str;
        
        return true;
    }
    
    // 测试is_system_power_on方法
    bool is_system_power_on() {
        // 使用设置的电源状态
        return (m_power_state == "ON");
    }
    
    // 测试update_quadruple_info_async方法
    void update_quadruple_info_async() {
        // 模拟异步更新逻辑
        m_quadruple_update_called = true;
        m_initial_delay_ms = 120000;  // 2分钟
        m_regular_interval_ms = 10000; // 10秒
    }
    
    // 测试on_quadruple_update_timer方法
    void on_quadruple_update_timer() {
        // 检查设备BDF是否有效
        if (m_pcie_device_bus == 0) {
            return;  // 无效BDF，跳过
        }
        
        // 检查电源状态
        if (!is_system_power_on()) {
            return;  // 电源关闭，跳过
        }
        
        // 获取四元组信息
        bool success = get_network_adapter_quadruple();
        if (success) {
            m_quadruple_update_success_count++;
        }
        
        // 处理首次更新逻辑
        if (m_first_quadruple_update) {
            m_first_quadruple_update = false;
            m_timer_interval_changed = true;
        }
    }
    
    // 获取测试结果
    const std::string& get_vendor_id_str() const { return m_vendor_id_str; }
    const std::string& get_device_id_str() const { return m_device_id_str; }
    const std::string& get_subsystem_vendor_id_str() const { return m_subsystem_vendor_id_str; }
    const std::string& get_subsystem_device_id_str() const { return m_subsystem_device_id_str; }
    bool get_quadruple_update_called() const { return m_quadruple_update_called; }
    int get_quadruple_update_success_count() const { return m_quadruple_update_success_count; }
    bool get_timer_interval_changed() const { return m_timer_interval_changed; }
    
private:
    std::shared_ptr<MockIMU> m_imu_obj;
    uint8_t m_system_id;
    uint8_t m_pcie_device_bus;
    uint8_t m_pcie_device_device;
    uint8_t m_pcie_device_function;
    uint8_t m_pcie_device_socket_id;
    std::string m_power_state;
    
    std::string m_vendor_id_str;
    std::string m_device_id_str;
    std::string m_subsystem_vendor_id_str;
    std::string m_subsystem_device_id_str;
    
    bool m_quadruple_update_called = false;
    int m_quadruple_update_success_count = 0;
    bool m_first_quadruple_update = true;
    bool m_timer_interval_changed = false;
    int m_initial_delay_ms = 0;
    int m_regular_interval_ms = 0;
};

// 测试新增方法的测试类
class Hi182xQuadrupleMethodTest : public testing::Test {
protected:
    void SetUp() override {
        m_card = std::make_unique<MockHi182xCard>();
    }
    
    void TearDown() override {
        m_card.reset();
    }
    
    std::unique_ptr<MockHi182xCard> m_card;
};

// 测试get_pcie_vid_did_info方法
TEST_F(Hi182xQuadrupleMethodTest, test_get_pcie_vid_did_info_success) {
    uint16_t vendor_id, device_id;
    bool result = m_card->get_pcie_vid_did_info(vendor_id, device_id);
    
    EXPECT_TRUE(result);
    EXPECT_EQ(vendor_id, 0x19e5);
    EXPECT_EQ(device_id, 0x1822);
}

// 测试get_pcie_svid_sdid_info方法
TEST_F(Hi182xQuadrupleMethodTest, test_get_pcie_svid_sdid_info_success) {
    uint16_t subsystem_vendor_id, subsystem_device_id;
    bool result = m_card->get_pcie_svid_sdid_info(subsystem_vendor_id, subsystem_device_id);
    
    EXPECT_TRUE(result);
    EXPECT_EQ(subsystem_vendor_id, 0x19e5);
    EXPECT_EQ(subsystem_device_id, 0x1823);
}

// 测试get_network_adapter_quadruple方法
TEST_F(Hi182xQuadrupleMethodTest, test_get_network_adapter_quadruple_success) {
    bool result = m_card->get_network_adapter_quadruple();
    
    EXPECT_TRUE(result);
    EXPECT_EQ(m_card->get_vendor_id_str(), "0x19e5");
    EXPECT_EQ(m_card->get_device_id_str(), "0x1822");
    EXPECT_EQ(m_card->get_subsystem_vendor_id_str(), "0x19e5");
    EXPECT_EQ(m_card->get_subsystem_device_id_str(), "0x1823");
}

// 测试is_system_power_on方法
TEST_F(Hi182xQuadrupleMethodTest, test_is_system_power_on) {
    bool result = m_card->is_system_power_on();
    EXPECT_TRUE(result);
}

// 测试update_quadruple_info_async方法
TEST_F(Hi182xQuadrupleMethodTest, test_update_quadruple_info_async) {
    m_card->update_quadruple_info_async();
    EXPECT_TRUE(m_card->get_quadruple_update_called());
}

// 测试on_quadruple_update_timer方法
TEST_F(Hi182xQuadrupleMethodTest, test_on_quadruple_update_timer_success) {
    // 测试正常情况下的定时器回调
    m_card->on_quadruple_update_timer();
    
    EXPECT_EQ(m_card->get_quadruple_update_success_count(), 1);
    EXPECT_TRUE(m_card->get_timer_interval_changed());
}

// 测试无效BDF的情况
TEST_F(Hi182xQuadrupleMethodTest, test_on_quadruple_update_timer_invalid_bdf) {
    // 创建无效BDF的卡片
    auto invalid_card = std::make_unique<MockHi182xCard>();
    invalid_card->set_invalid_bdf();
    
    // 调用定时器回调
    invalid_card->on_quadruple_update_timer();
    
    // 应该不会更新四元组信息
    EXPECT_EQ(invalid_card->get_quadruple_update_success_count(), 0);
}

// 测试电源关闭的情况
TEST_F(Hi182xQuadrupleMethodTest, test_on_quadruple_update_timer_power_off) {
    // 创建电源关闭的卡片
    auto power_off_card = std::make_unique<MockHi182xCard>();
    power_off_card->set_power_off();
    
    // 调用定时器回调
    power_off_card->on_quadruple_update_timer();
    
    // 应该不会更新四元组信息
    EXPECT_EQ(power_off_card->get_quadruple_update_success_count(), 0);
}

// 测试IMU未初始化的情况
TEST_F(Hi182xQuadrupleMethodTest, test_imu_not_initialized) {
    // 创建没有IMU对象的卡片
    auto no_imu_card = std::make_unique<MockHi182xCard>();
    no_imu_card->clear_imu();
    
    uint16_t vendor_id, device_id;
    bool result = no_imu_card->get_pcie_vid_did_info(vendor_id, device_id);
    
    EXPECT_FALSE(result);
}

} // namespace dev
